#include <stdio.h>

// ============= 第三课：指针与函数 =============
// 学习如何通过指针向函数传递参数，实现引用传递

// 函数声明
void swap_by_value(int a, int b);           // 值传递（无法交换）
void swap_by_pointer(int *a, int *b);       // 指针传递（可以交换）
void modify_array(int arr[], int size);     // 数组传递（实际是指针）
void print_array(int *arr, int size);       // 用指针接收数组
int find_max(int *arr, int size, int **max_ptr); // 返回最大值的指针
void calculate_stats(int *arr, int size, int *sum, float *avg, int *max, int *min);

int main(void) {
    printf("=== C语言指针学习 - 第三课：指针与函数 ===\n\n");
    
    // 1. 值传递 vs 指针传递
    printf("1. 值传递 vs 指针传递：\n");
    int x = 10, y = 20;
    printf("   交换前: x = %d, y = %d\n", x, y);
    
    printf("   尝试值传递交换:\n");
    swap_by_value(x, y);
    printf("   交换后: x = %d, y = %d (没有改变!)\n", x, y);
    
    printf("   使用指针传递交换:\n");
    swap_by_pointer(&x, &y);
    printf("   交换后: x = %d, y = %d (成功交换!)\n", x, y);
    printf("\n");
    
    // 2. 数组与函数
    printf("2. 数组与函数：\n");
    int numbers[5] = {1, 2, 3, 4, 5};
    printf("   原数组: ");
    print_array(numbers, 5);
    
    printf("   修改数组中的每个元素 (乘以2):\n");
    modify_array(numbers, 5);
    printf("   修改后: ");
    print_array(numbers, 5);
    printf("\n");
    
    // 3. 返回指针的函数
    printf("3. 返回指针的函数：\n");
    int data[6] = {15, 8, 23, 42, 4, 16};
    int *max_element_ptr;
    
    int max_value = find_max(data, 6, &max_element_ptr);
    printf("   数组: ");
    print_array(data, 6);
    printf("   最大值: %d\n", max_value);
    printf("   最大值的地址: %p\n", (void*)max_element_ptr);
    printf("   通过指针访问最大值: %d\n", *max_element_ptr);
    printf("\n");
    
    // 4. 多个返回值（通过指针参数）
    printf("4. 通过指针参数返回多个值：\n");
    int sum, max, min;
    float avg;
    
    calculate_stats(data, 6, &sum, &avg, &max, &min);
    printf("   数组: ");
    print_array(data, 6);
    printf("   统计结果:\n");
    printf("   - 总和: %d\n", sum);
    printf("   - 平均值: %.2f\n", avg);
    printf("   - 最大值: %d\n", max);
    printf("   - 最小值: %d\n", min);
    printf("\n");
    
    // 5. 指针参数的安全检查
    printf("5. 指针参数的安全检查：\n");
    printf("   好的编程实践：在函数中检查指针是否为NULL\n");
    printf("   示例：在swap_by_pointer函数中检查指针有效性\n");
    
    int *null_ptr = NULL;
    printf("   尝试传递NULL指针:\n");
    swap_by_pointer(null_ptr, &x);  // 函数内部会检查并处理
    printf("\n");
    
    printf("=== 第三课总结 ===\n");
    printf("1. 值传递：函数接收参数的副本，无法修改原变量\n");
    printf("2. 指针传递：函数接收变量的地址，可以修改原变量\n");
    printf("3. 数组传递给函数时，实际传递的是指向第一个元素的指针\n");
    printf("4. 函数可以返回指针，实现多个返回值\n");
    printf("5. 使用指针参数前应该检查其有效性\n");
    printf("6. 通过指针参数，一个函数可以返回多个值\n");
    
    return 0;
}

// 值传递函数 - 无法交换原变量的值
void swap_by_value(int a, int b) {
    printf("     函数内部交换前: a = %d, b = %d\n", a, b);
    int temp = a;
    a = b;
    b = temp;
    printf("     函数内部交换后: a = %d, b = %d\n", a, b);
    printf("     (只是交换了副本，原变量不受影响)\n");
}

// 指针传递函数 - 可以交换原变量的值
void swap_by_pointer(int *a, int *b) {
    // 安全检查
    if (a == NULL || b == NULL) {
        printf("     错误：传入了NULL指针，无法进行交换\n");
        return;
    }
    
    printf("     函数内部交换前: *a = %d, *b = %d\n", *a, *b);
    int temp = *a;
    *a = *b;
    *b = temp;
    printf("     函数内部交换后: *a = %d, *b = %d\n", *a, *b);
    printf("     (通过指针修改了原变量的值)\n");
}

// 修改数组的函数
void modify_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // 每个元素乘以2
    }
}

// 打印数组的函数
void print_array(int *arr, int size) {
    printf("[");
    for (int i = 0; i < size; i++) {
        printf("%d", arr[i]);
        if (i < size - 1) printf(", ");
    }
    printf("]\n");
}

// 找到最大值并返回其指针
int find_max(int *arr, int size, int **max_ptr) {
    if (arr == NULL || size <= 0) {
        *max_ptr = NULL;
        return 0;
    }
    
    *max_ptr = arr;  // 指向第一个元素
    int max_value = arr[0];
    
    for (int i = 1; i < size; i++) {
        if (arr[i] > max_value) {
            max_value = arr[i];
            *max_ptr = &arr[i];  // 更新指针指向最大值
        }
    }
    
    return max_value;
}

// 计算数组统计信息的函数
void calculate_stats(int *arr, int size, int *sum, float *avg, int *max, int *min) {
    if (arr == NULL || size <= 0) {
        return;
    }
    
    *sum = 0;
    *max = arr[0];
    *min = arr[0];
    
    for (int i = 0; i < size; i++) {
        *sum += arr[i];
        if (arr[i] > *max) *max = arr[i];
        if (arr[i] < *min) *min = arr[i];
    }
    
    *avg = (float)*sum / size;
} 